// 泛型
// 泛型的基本示例
// 为 join 方法定义泛型 T （泛型一般使用 T 来表示），作用：该方法的数据类型不固定，由调用方法时定义
function join<T>(first: T, second: T) {
  return `${first}${second}`
}
join<string>('LTY', 'hello') // 使用泛型方法时再指定参数类型
// 泛型可以定义多个
function join2<T, N>(first: T, second: N) {
  return `${first}${second}`
}
join2<string, number>('LTY', 101) // 使用泛型方法时再指定参数类型
// 泛型中数组的用法：
function myArr<T>(list: Array<T>) {
  return list
}
// 还可以写成下面这样：
function myArr2<T>(list: []) {}

myArr<string>(['red', 'blue', 'yellow']) // 使用泛型方法时再指定参数类型

// 泛型的继承
interface UserName {
  name: string
}
// 这里让 T 继承自 UserName 表示，这个类型中必须要有一个 name 的属性
class GetUser<T extends UserName> {
  constructor(private users: T[]) {}
  getName(index: number): string {
    return this.users[index].name
  }
}
const getUser = new GetUser([
  { name: '小明' },
  { name: '小红' },
  { name: '小唐' },
])
console.log(getUser.getName(2))

// 泛型约束
// 这里的 getText 方法的参数类型使用了泛型，但是我们对这个泛型进行了约束，只能是 string 或者 number
function getText<T extends string | number>(data: T) {
  if (typeof data === 'string') {
    return console.log('这是一个字符串')
  } else {
    return console.log('这是一个数字')
  }
}
getText('abc')
getText(123)
